#define MAX_CUSTOMER 60

int customerConditionVariable[MAX_CUSTOMER];
int popAmount[MAX_CUSTOMER];
int sodaAmount[MAX_CUSTOMER];
int foodReportCount[MAX_CUSTOMER];
int custPositions[MAX_CUSTOMER][4][2];	/*holds the customers' positions in the theater*/
int custsInBathroom[MAX_CUSTOMER];
int inBathroom[MAX_CUSTOMER][4];

int customerLock[MAX_CUSTOMER];
int headCustomerCondition[MAX_CUSTOMER];

int customersInGroup[MAX_CUSTOMER];

int customersInGroupLock;


int numberOfCustomers;
int numberOfCustomersCV;


int numberOfCustomersLock;
struct CustData custDataArray[MAX_CUSTOMER];

int groupTotal = 0;
	

/*
Shared Data I use:
	ticketClerkLineLock
	ticketClerkState[]
	ticketClerkLineCount[]
	ticketClerkLineCV[]
*/






/*prototype*/
void MiniCustomer(int IDNums[3]);

void CustomerAgent(/*int GroupNum*/) {	/*parameters: size of group, group number*/
	
	/*DATA*/
	int num;

	int goodRow1;
	int goodRowNumber;

	int shortestTakerLine;

	int shortestFoodLine;

	int shortestTicketLine;
	/*describes when the customer is supposed to find a new, shorter line*/
	int newLine;
	
	/*describes when the customer is in the lobby after the film (waiting to leave instead of waiting for next film)*/
	int seenFilm;
	
	/*says if the group has bought tickets*/
	int hasTickets;

	/*tells if the customers got food*/
	int hasFood;

	/*says if the customer has found seats*/
	int seated;
	
	/*total amount owed when ordering something (concessions/tickets)*/
	int myTotal;
	
	/*references to current clerk types (which position they are in the global arrays of clerks)*/
	int myTicketClerk;
	int myFoodClerk;
	int myTicketTaker;
	int ia[4][3];
	int groupNum;
	int custSize;
	int i ,j;
	int ID;
	int customersBusy[5];
	
	/*waits movie theater so that everything will only start when their data has been initialized*/
	/*LockAcquire(initialLock);
	LockRelease(initialLock);*/
	Write("Customer is Made\n",18,1);
	 /*this is where the customer gets its unique id*/
	LockAcquire(numberOfCustomersLock);
	groupNum = numberOfCustomers;
	numberOfCustomers++;
	LockRelease(numberOfCustomersLock);

	if(groupNum+1 == groupTotal) {
		Signal(theaterCV, theaterLock);
	}

	Write("What is happening?\n",20,1);
	LockAcquire(customerLock[groupNum]);
	
	
	/*number assigned to a group, only ever used in print statements*/
	ID = groupNum;
	
	/*Number of customers in this group*/


	/*Array holding the states of the individual customers*/
		/*0 = Free, 1 = Busy, -1 = Not there*/
	
	

	/*initialize lock*/


	/*initialize condition variable*/

	/*initialize threads*/
	
	
	/*Constructor*/
		newLine = 0;
		seenFilm = 0;
		hasTickets = 0;
		hasFood = 0;
		seated = 0;
		myTotal = 0;

		custsInBathroom[groupNum]=0;
		
		/*initialized to -1 (doesn't have a clerk yet)*/
		myTicketClerk = -1;
		myFoodClerk = -1;
		myTicketTaker = -1;
		
		/*initialize customer array to default values (assuming only the leader exists)*/
		customersBusy[0] = 0;
		for(i = 1; i < 5; i++) {
			customersBusy[i] = -1;
		}
		/*define how many customers there are (1-5) and set those that exist to 0*/
		custSize = custDataArray[groupNum].groupSize;
		

		for(i = 1; i < custSize; i++) {
			customersBusy[i] = 0;
		}

		/*fills the positions array with -1s since they don't occupy any positions in theater*/
		for(i = 0; i < 5; i++) {
			for(j = 0; j < 2; j++) {
				custPositions[groupNum][i][j] = -1;
			}
		}

		/*printf("Head customer in group %i has entered the theater\n",groupNum);*/
		Write1("Head customer in group %i has entered othe theater\n", 51, 1, groupNum);


	LockRelease(customerLock[groupNum]);

	/*And so it begins...*/

	/*CUSTOMER-TICKET CLERK INTERACTION: GETTING IN LINE*/
	/*
	Shared Data used here:
		ticketClerkLineLock
		ticketClerkState[]
		ticketClerkLineCount[]
		ticketClerkLineConditionVariables[]
	*/

	do{
		/*Look at lines and get in shortest one*/

		
		/*see if there are any empty lines*/
		myTicketClerk = -1;	/*reset this to -1 so that i can correctly check when i've found a line*/
		for(i = 0; i < ticketClerks; i++) {
			LockAcquire(ticketClerkLocks[i]);
			if(ticketClerkState[i] == available) {
				/*Found ticket clerk that is available (0)*/
				/*Line cannot be shorter so enter line*/
				myTicketClerk = i;
				ticketClerkState[myTicketClerk] = busy;
				LockRelease(ticketClerkLocks[i]);
				break;
			}
			LockRelease(ticketClerkLocks[i]);
		}
		LockAcquire(ticketClerkLineLock);

		/*holds position of shortest line*/
		shortestTicketLine = -1;
		/*check if I found an empty line*/

		if(myTicketClerk == -1) {
			/*look for shortest line*/
			
			int shortestLineLength = 9999;
			for(i = 0; i < ticketClerks; i++) {
				if(ticketClerkLineCount[i] == 0 && ticketClerkState[i] == busy)
				{
					shortestTicketLine = i;
					break;
				}
				if(shortestLineLength > ticketClerkLineCount[i] && ticketClerkState[i] == busy) {
					shortestTicketLine = i;
					shortestLineLength = ticketClerkLineCount[i];
				}
			}
			/*must have shortest line at this point*/
			myTicketClerk = shortestTicketLine;
			/*get in that line*/
			ticketClerkLineCount[myTicketClerk]++;	/*increment my line's size*/

			Write1("Head customer in group %i is getting in Ticket Clerk line ", 58, 1, groupNum);
			Write1("%i\n", 4, 1, myTicketClerk);	/*puts the thread to sleep and waits for a signal from the ticket clerk when I'm at the front of the line*/
			Wait(ticketClerkLineConditionVariables[myTicketClerk], ticketClerkLineLock);
		}
		else{
			LockRelease(ticketClerkLineLock);
		}
		if(ticketClerkState[myTicketClerk]==on_break)
		{
			
			Write1("Head customer of group %i sees ticket clerk ", 24, 1, groupNum);
			Write1("%i is on break and must find new line.\n", 20, 1, myTicketClerk);
		}
			

	}while(ticketClerkState[myTicketClerk] == on_break);	/*if clerk goes on break, customer gets broadcast and starts over*/


	/*CUSTOMER-TICKET CLERK INTERACTION: BUYING TICKETS*/
	/*
	Shared Data used here:
		ticketClerkLocks[]
		ticketClerkState[]
		ticketsBeingSold[]
		ticketClerkCV[]
	*/
				
	LockAcquire(ticketClerkLocks[myTicketClerk]);
	ticketClerkState[myTicketClerk] = busy;


	/*pass number of tickets and wake up clerk*/
	/*printf("Head customer in group %i is wallking up to ticket clerk %i to buy %i tickets\n",groupNum,myTicketClerk,custSize);*/
	Write1("Head customer in group %i is wallking up to ticket clerk ", 57, 1, groupNum);
	Write1("%i to buy ", 10, 1, myTicketClerk);
	Write1("%i tickets\n",12 ,1, custSize);
	ticketsBeingSold[myTicketClerk] = custSize;
	/*And now I wait for the clerk's response (asking to be paid)*/
	Signal(ticketClerkConditionVariables[myTicketClerk], ticketClerkLocks[myTicketClerk]);
	Wait(ticketClerkConditionVariables[myTicketClerk], ticketClerkLocks[myTicketClerk]);
	
	/*Pay the clerk*/

	LockAcquire(ticketClerkLocks[myTicketClerk]);
	ticketEarnings[myTicketClerk] += ticketsTotal[myTicketClerk];	/*adding the total given by the clerk to the clerk's earnings (simulating paying him)*/
	/*Wait again for clerk's reponse (telling me to leave)*/
	Signal(ticketClerkConditionVariables[myTicketClerk], ticketClerkLocks[myTicketClerk]);
	Wait(ticketClerkConditionVariables[myTicketClerk], ticketClerkLocks[myTicketClerk]);
	LockAcquire(customerLock[groupNum]);
	Write1("Customer %i is walking away from Ticket Clerk\n",47,1,groupNum);
	/*Leave the clerk (DON'T ACQUIRE HIS LOCK) and go to the food clerk*/
	
	/*CUSTOMER-FOOD CLERK INTERACTION: GETTING IN LINE - RETURN OF LINE*/
	/*
	Shared Data used here:
		foodClerkLineLock
		foodClerkStates[]
		foodClerkLineCount[]
		foodClerkLineConditionVariables[]
	*/

	/*each mini cust tells the head cust how much food they want*/
	if(custSize>1)
	{
		Broadcast(customerConditionVariable[groupNum], customerLock[groupNum]);
		Wait(customerConditionVariable[groupNum], customerLock[groupNum]);
	}
		
	
	
	/*actually buying food (if you need to)*/
	LockAcquire(customerLock[groupNum]);
	Write1("Customer %i is approaching Food Clerk\n",39,1,groupNum);
	j = rand() % 100;
	if(j < 75) {
		popAmount[groupNum]++;

	}
	j = rand() % 100;
	if(j < 75) {
		sodaAmount[groupNum]++;
	}
	if(popAmount[groupNum] != 0 || sodaAmount[groupNum] != 0) {
		LockRelease(customerLock[groupNum]);
		do{
			/*Look at lines and get in shortest one*/
			LockAcquire(foodClerkLineLock);

			/*see if there are any empty lines*/
			for(i = 0; i < foodClerks; i++) {
				if(foodClerkStates[i] == available) {
					/*Found food clerk that is available (0)*/
					/*Line cannot be shorter so enter line*/
					myFoodClerk = i;
					foodClerkStates[myFoodClerk] = busy;
					break;
				}
			}

			/*holds position of shortest line*/
			shortestFoodLine = -1;
			/*check if I found an empty line*/
			if(myFoodClerk == -1) {
				/*look for shortest line*/
				int shortestLineLength = 9999;
				for(i = 0; i < foodClerks; i++ &&  foodClerkStates[i] == busy) {
					if(foodClerkLineCount[i]==0)
					{
						shortestFoodLine = i;
						break;
					}
					if(shortestLineLength > foodClerkLineCount[i]) {
						shortestFoodLine = i;
						shortestLineLength = foodClerkLineCount[i];
					}
				}

				/*must have shortest line at this point*/
				myFoodClerk = shortestFoodLine;
				/*get in that line*/
				foodClerkLineCount[myFoodClerk]++;	/*increment my line's size*/
				/*printf("Head customer in group %i is getting in Food  Clerk line %i\n",groupNum,myFoodClerk);*/
				Write1("Head customer in group %i is getting in Food Clerk line", 55, 1, groupNum);
				Write1("%i\n", 4, 1, myFoodClerk);
				Wait(foodClerkLineConditionVariables[myFoodClerk], foodClerkLineLock);	/*puts the thread to sleep and waits for a signal from the food clerk when I'm at the front of the line*/
			}
			else
				LockRelease(foodClerkLineLock);
			if(foodClerkStates[myFoodClerk]==on_break)
			{
				/*printf("Head customer of group %i sees food clerk %i is on break and must find new line\n",groupNum,myFoodClerk);*/
				Write1("Head customer of group %i sees food clerk ", 42, 1, groupNum);
				Write1("%i is on break and must find new line\n", 39, 1, myFoodClerk);
			}
		}while(foodClerkStates[myFoodClerk] == on_break);	/*if clerk goes on break, customer gets broadcast and starts over*/

		

		/*CUSTOMER-FOOD CLERK INTERACTION: BUYING FOOD*/
		/*
		Shared Data used here:
			foodClerkLock[]
			popcornBeingSold[]
			sodaBeingSold[]
			foodClerkConditionVariables[]
		*/

		LockAcquire(customerLock[groupNum]);
		LockAcquire(foodClerkLocks[myFoodClerk]);
		Write1("Head customer in group %i is walking up to food clerk ", 64, 1, groupNum);
		Write1("%i to order ", 12, 1, myFoodClerk);
		Write1("%i popcorn and ", 15, 1, popAmount[groupNum]);
		Write1("%i soda\n", 9, 1, sodaAmount[groupNum]);
		/*pass popcorn amount and wake up clerk*/
		
		Write1("Head Customer %i is ordering ",29,1,groupNum);
		Write1("%i popcorn\n",12,1,sodaAmount[groupNum]);
		popcornBeingSold[myFoodClerk] = popAmount[groupNum];
		LockRelease(customerLock[groupNum]);
		/*And now I wait for the clerk's response (waiting for confirmation)*/
		Signal(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
		Wait(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
		
		LockAcquire(foodClerkLocks[myFoodClerk]);
		
		Write1("Head Customer %i is ordering ",29,1,groupNum);
		Write1("%i soda\n",9,1,sodaAmount[groupNum]);
		
		/*pass soda amount and wake up clerk*/
		sodaBeingSold[myFoodClerk] = sodaAmount[groupNum];
		/*wait for clerk's response (giving me food)*/


		Signal(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
		Wait(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
	 	     
		/*should have food by now*/
		hasFood = 1;

		/*Pay the clerk*/
		LockAcquire(foodClerkLocks[myFoodClerk]);
		foodEarnings[myFoodClerk] += foodTotal[myFoodClerk];	/*adding the total given by the clerk to the clerk's earnings (simulating paying him)*/
		/*Wait again for clerk's reponse (telling me to leave)*/
		/*printf("Head customer %i is paying %i to food clerk %i\n",groupNum,foodTotal[myFoodClerk],myFoodClerk);*/
		Write1("Head customer %i ", 17, 1, groupNum);
		Write1("is paying food clerk", 20, 1, foodTotal[myFoodClerk]);
		Write1("%i\n", 4, 1, myFoodClerk);
		Signal(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
		Wait(foodClerkConditionVariables[myFoodClerk], foodClerkLocks[myFoodClerk]);
		/*printf("Head customer %i is leaving food clerk %i\n",groupNum,myFoodClerk);*/
		Write1("Head customer %i ", 17, 1, groupNum);
		Write1("is leaving food clerk %i\n", 26, 1, myFoodClerk);
	}
	else
		LockRelease(customerLock[groupNum]);


	/*leave the food clerk and go to the ticket clerk*/
	
	/*CUSTOMER-TICKET TAKER INTERACTION: GETTING IN LINE - THE FINAL CHAPTER*/
	/*
	Shared Data used here:
		ticketTakerLineLock
		ticketTakerStates[]
		ticketTakerLineCount[]
		ticketTakerLineConditionVariables[]
	*/
			
	customersServed++;
					
takerLine:
	do{
		/*Look at lines and get in shortest one*/
		LockAcquire(ticketTakerLineLock);
		/*see if there are any empty lines*/
		for(i = 0; i < ticketTakers; i++) {
			LockAcquire(ticketTakerLocks[i]);
			if(ticketTakerStates[i] == available) {
					
				/*Found ticket taker that is available (0)*/
				/*Line cannot be shorter so enter line*/
				Write("Checking TT\n", 13, 1);
				myTicketTaker = i;
				ticketTakerStates[myTicketTaker] = busy;
				break;
				LockRelease(ticketTakerLocks[i]);
			}
			LockRelease(ticketTakerLocks[i]);
		}
			
		/*holds position of shortest line*/
		shortestTakerLine = -1;
		/*check if I found an empty line*/
	
		if(myTicketTaker == -1) {
			
			/*look for shortest line*/
			int shortestLineLength = 9999;
			for(i = 0; i < ticketTakers; i++ && ticketTakerStates[i] == busy) {
				if(ticketTakerLineCount[i]==0)
				{
					shortestTakerLine=i;
					break;
				}
				if(shortestLineLength > ticketTakerLineCount[i]) {
					shortestTakerLine = i;
					shortestLineLength = ticketTakerLineCount[i];
				}
			}

			/*must have shortest line at this point*/
			myTicketTaker = shortestTakerLine;
			/*get in that line*/
			Write1("Head Customer in Group %i is getting in TicketTaker line ", 57, 1, groupNum);
			Write1("%i\n", 4, 1, myTicketTaker);
			ticketTakerLineCount[myTicketTaker]++;	/*increment my line's size*/
			Wait(ticketTakerLineConditionVariables[myTicketTaker], ticketTakerLineLock);	/*puts the thread to sleep and waits for a signal from the ticket taker when I'm at the front of the line*/
			
		}
		else
			LockRelease(ticketTakerLineLock);

	}while(ticketTakerStates[myTicketTaker] == on_break);	/*if clerk goes on break, customer gets broadcast and starts over*/
	/*CUSTOMER-TICKET TAKER INTERACTION: GIVING TICKETS*/
	/*
	Shared Data used here:
		ticketTakerLocks[]
		ticketTakerConditionVariables[]
	*/



	LockAcquire(ticketTakerLocks[myTicketTaker]);

	/*pass number of tickets*/
	numberOfTickets[myTicketTaker] = custSize;
	/*And now I wait for the taker's response (telling me to go in or not)*/
	
	Signal(ticketTakerConditionVariables[myTicketTaker], ticketTakerLocks[myTicketTaker]);
	Wait(ticketTakerConditionVariables[myTicketTaker], ticketTakerLocks[myTicketTaker]);

	/*wait or go in depending on if the theater is full*/
	
	LockAcquire(takingTicketsLock);
	LockAcquire(ticketTakerLocks[myTicketTaker]);


	if(dontGoIn[myTicketTaker]) {
		Signal(ticketTakerConditionVariables[myTicketTaker], takingTicketsLock);
		LockRelease(ticketTakerLocks[myTicketTaker]);
		Wait(lobbyCV, takingTicketsLock);
		myTicketTaker=-1;
		Write("FUCK\n", 6, 1);
		goto takerLine;
	}
	Signal(ticketTakerConditionVariables[myTicketTaker], takingTicketsLock);
	LockRelease(ticketTakerLocks[myTicketTaker]);
	LockRelease(takingTicketsLock);
	
	/*CUSTOMER-THEATER INTERACTION: SIT YOU DOWN BOY*/
	/*
	Shared Data used here:
		seatsFreeLock
		seats[][]
		seatsFree[]
	*/
	
	/*go into theater*/

	LockAcquire(seatsFreeLock);
	/*find the row with the most seats*/
	goodRow1 = seatsFree[0];
	goodRowNumber = 0;
	for(i = 1; i < 5; i++) {
		if(seatsFree[i] > goodRow1) {
			goodRow1 = seatsFree[i];
			goodRowNumber = i;
		}
	}
	custsSeated++;
	num = 0;	/*counter*/
	/*look for 5 in a row*/
	for(i = 5-goodRow1; i < 5; i++) {	/*this is where we get in the seats. it is rather complicated.*/
		if(i==5-goodRow1)
		{
			seats[goodRowNumber][i] = 0;
		}
		/*record position*/
		custPositions[groupNum][num][0] = goodRowNumber;
		custPositions[groupNum][num][1] = i;
		num++;

		if(num == custSize) {
			seated = 1;
			goto seated;
		}
	}
	
	if(goodRowNumber==4)
	{
		for(j=1;j<5;j++)
		{
			for(i = 5-seatsFree[goodRowNumber-j]; i < 5; i++) 
			{	
				/*record position*/
				custPositions[groupNum][num][0] = goodRowNumber-j;
				custPositions[groupNum][num][1] = i;
				num++;

				if(num == custSize) {
					seated = 1;
					goto seated;
			}
		}
		}
	}

	else if(goodRowNumber==0)
	{
		for(j=1;j<5;j++)
		{
			for(i = 5-seatsFree[goodRowNumber+j]; i < 5; i++) 
			{	
				/*record position*/
				custPositions[groupNum][num][0] = goodRowNumber+j;
				custPositions[groupNum][num][1] = i;
				num++;

				if(num == custSize) {
					seated = 1;
					goto seated;
			}
		}
		}
	}

	else
	{
		for(j=1; j<3; j++)
		{
			if((goodRowNumber-j)>-1)
			{
				for(i = 5-seatsFree[goodRowNumber-j]; i < 5; i++) 
				{	
					/*record position*/
					custPositions[groupNum][num][0] = goodRowNumber-j;
					custPositions[groupNum][num][1] = i;
					num++;

					if(num == custSize)
					{
						seated = 1;
						goto seated;
					}
				}
			}

			if(goodRowNumber+j<5)
			{
				for(i = 5-seatsFree[goodRowNumber+j]; i < 5; i++) 
				{	
					/*record position*/
					custPositions[groupNum][num][0] = goodRowNumber+j;
					custPositions[groupNum][num][1] = i;
					num++;

					if(num == custSize)
					{
						seated = 1;
						goto seated;
					}
				}
			}
		}
			
	}
	

seated:	/*jump to here when you're seated*/
				
	seatedPeople+=custSize;
	
	Broadcast(customerConditionVariable[groupNum], customerLock[groupNum]);
	/*CUSTOMER-TECH INTERACTION: SHITTY MINISERIES*/
	/*
	Shared Data used here:
		techMovieVariable
	*/

	/*watch movie and wait for it to finish*/
	Wait(techMovieVariable, seatsFreeLock);
	ticketsTaken--;
	custsSeated--;
	Yield();

	j = rand() % 4;
	if(j==0)
	{
		for(i = 0; i<50;i++)
		{
			Yield();
		}
	}
	
	LockAcquire(customerLock[groupNum]);

	/*CUSTOMER-THEATER INTERACTION: INCEPTION 2 - GET OUT THE DREAM IS COLLAPSING*/
	/*
	Shared Data used here:
		seats[][]
	*/

	Broadcast(customerConditionVariable[groupNum], customerLock[groupNum]);

	Write1("Head customer in group %i is leaving the theater\n", 50, 1, groupNum);
	numberOfCustomers--;
	Exit(0);
	}





void MiniCustomer(int IDNums[3]) 
{
	int miniGroupNum;
	int miniCustNum;
	int miniCustSize;
	int popcorn;
	int soda;
	int j;
	
	/*get the customer group's unique id*/
	LockAcquire(numberOfCustomersLock);
	miniGroupNum = numberOfCustomers;
	LockRelease(numberOfCustomersLock);
	
	/**/
	LockAcquire(customersInGroupLock);
	miniCustNum = customersInGroup[miniGroupNum];
	customersInGroup[miniGroupNum]++;
	LockRelease(customersInGroupLock);
	
	miniCustSize = custDataArray[miniGroupNum].groupSize;
	LockAcquire(customerLock[miniGroupNum]);
	if(custDataArray[miniGroupNum].groupSize-1==customersInGroup[miniGroupNum])
	{
		Signal(numberOfCustomersCV,numberOfCustomersLock);
	}

	Write1("Customer %i in group ", 21, 1, miniCustNum);
	Write1("%i has entered the theater\n", 28, 1, miniGroupNum);
	if(miniCustNum>5||miniCustNum<0)
	{
		/*Write1("Cust Num is %i\n", 16, 1, miniCustNum);*/
	}
	Write1("Mini Group Num is %i\n",22,1,miniGroupNum);
	Wait(customerConditionVariable[miniGroupNum], customerLock[miniGroupNum]);

	LockAcquire(customerLock[miniGroupNum]);
	popcorn=0;
	soda=0;
	/*determine how much popcorn and soda to buy using randomness*/
	j = rand() % 100;
	if(j < 75) {
		popAmount[miniGroupNum]++;
		popcorn=1;
	}
	j = rand() % 100;
	if(j < 75) {
		sodaAmount[miniGroupNum]++;
		soda=1;
	}

	Write1("Customer %i in group ", 21, 1, miniCustNum);
	Write1("%i wants ", 9, 1, miniGroupNum);
	Write1("%i popcorn and ", 15, 1, popcorn);
	Write1("%i soda\n", 9, 1, soda);

	foodReportCount[miniGroupNum]++;
	if(foodReportCount[miniGroupNum] == miniCustSize-1) {
		/*release that food lock I'm holding and go back to sleep*/
		Signal(customerConditionVariable[miniGroupNum], customerLock[miniGroupNum]);
	}
	
	Wait(customerConditionVariable[miniGroupNum], customerLock[miniGroupNum]);


	LockAcquire(seatsFreeLock);
	LockAcquire(customerLock[miniGroupNum]);
	
	Write1("Customer %i in group ", 21, 1, miniCustNum);
	Write1("%i is sitting in a seat\n", 25, 1, miniGroupNum);
	seats[custPositions[miniGroupNum][miniCustNum][0]][custPositions[miniGroupNum][miniCustNum][1]] = 0;
	custsSeated++;
	
	LockRelease(customerLock[miniGroupNum]);
	Wait(techMovieVariable, seatsFreeLock); 
	

	/*get out of your seats*/
	Write1("Customer %i in group ", 21, 1, miniCustNum);
	Write1("%i is getting out of his seat\n", 31, 1, miniGroupNum);
	seats[custPositions[miniGroupNum][miniCustNum][0]][custPositions[miniGroupNum][miniCustNum][1]] = 1;
	ticketsTaken--;
	custsSeated--;

	

	j = rand() % 4;
	LockAcquire(customerLock[miniGroupNum]);
	if(j==0)
	{
		/*Write1("%s ", 3, 1, currentThread->getName());*/
		Write1("Customer Thread %i is going to bathroom\n", 25, 1, miniGroupNum);


		
		if(custsInBathroom[miniGroupNum]==0)
		{
			Signal(headCustomerCondition[miniGroupNum], customerLock[miniGroupNum]);
		}
	}
	Wait(customerConditionVariable[miniGroupNum], customerLock[miniGroupNum]);
	Exit(0);
}

